#include "db/user.h"
#include "jwt.h"

#include <sys/stat.h>
#include <sys/random.h>
#include <crypt.h>

int recvuser(UserInfo_t *user, Client_t *cli)
{
    int ret = recvAll(cli->socket_fd, user, sizeof(UserInfo_t), 0);
    PRINT_DEBUG("username = %s userpass = %s", user->name, user->password);
    // 更新当前路径并创建对应目录
    strcpy(cli->cur_path, "/");
    return ret;
}

void inserthome(MYSQL *conn, Client_t *cli)
{
    char sql_select[512] = {0};
    char sql_insert[1024] = {0};
    MYSQL_RES *result = NULL;
    MYSQL_ROW row;

    // 拿到user_id
    sprintf(sql_select, "select user_id from users where username = '%s'", cli->user_info.name);
    result = excutesql(sql_select, conn);
    row = mysql_fetch_row(result);
    int user_id = atoi(row[0]);

    // 判断路径是否存在
    memset(sql_select, 0, sizeof(sql_select));
    sprintf(sql_select, "select file_path from files where user_id = %d", user_id);

    result = excutesql(sql_select, conn);
    memset(&row, 0, sizeof(MYSQL_ROW));
    row = mysql_fetch_row(result);
    if (row != NULL)
    {
        return;
    }

    sprintf(sql_insert, "insert into files (user_id, parent_id, file_name, file_path, file_type) values(%d, %d, '%s', '/', %d)",
            user_id, -1, cli->user_info.name, 1);
    excutesql(sql_insert, conn);
}

static void generateSalt(char *salt, size_t length)
{
    const char charset[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
    size_t charsetSize = sizeof(charset) - 1;

    unsigned char randBytes[length];
    if (getrandom(randBytes, length, 0) == -1)
    {
        perror("getrandom");
        exit(EXIT_FAILURE);
    }

    for (size_t i = 0; i < length; ++i)
    {
        salt[i] = charset[randBytes[i] % charsetSize];
    }
    salt[length] = '\0';
}

int insertUsers(MYSQL *conn, UserInfo_t *user)
{
    char queries[512] = {0};
    char salt[9] = {0}; // 这里必须是9
    generateSalt(salt, 8);
    char std_salt[13] = {0};
    sprintf(std_salt, "$5$%s$", salt);
    char *encrypted = crypt(user->password, std_salt);
    if (encrypted == NULL)
    {
        perror("计算失败 \n");
        return -1;
    }
    sprintf(queries, "insert into users (username, password_hash, salt) values ( '%s', '%s', '%s' )", user->name, encrypted, std_salt);
    int ret_query = mysql_query(conn, queries);
    return ret_query;
}

int authUser(MYSQL *conn, UserInfo_t *user)
{
    char queries[512] = {0};
    sprintf(queries, "select salt,password_hash from users where username = '%s'", user->name);
    MYSQL_RES *result = NULL;
    result = excutesql(queries, conn);
    MYSQL_ROW row;
    memset(&row, 0, sizeof(MYSQL_ROW));
    row = mysql_fetch_row(result);
    if (row == NULL)
    {
        PRINT_DEBUG("找不到对应用户：%s", user->name);
        return -1;
    }

    char salt[13] = {0};
    strncpy(salt, row[0], 12);
    char password_hash[56] = {0};
    strncpy(password_hash, row[1], 55);

    char *encrypted = crypt(user->password, salt);
    if (strcmp(password_hash, encrypted) != 0)
    {
        PRINT_DEBUG("密码错误：%s, %s", user->name, encrypted);
        return -2;
    }
    else
    {
        PRINT_DEBUG("登录成功！");

        char *jwt = encodeJWT(user->name);
        // PRINT_DEBUG("jwt: %s\n", jwt);
        strcpy(user->jwt_token, jwt);
        // char aud[256] = {0};
        // strcpy(aud, user->name);
        // decodeJWT(jwt, secret_key, aud);
        free(jwt);

        return 0;
    }
}